package com.fly.refresh;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.ResourceBundle;
import java.util.concurrent.ScheduledThreadPoolExecutor;

import javax.annotation.PostConstruct;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

/**
 * 配置文件实时刷新
 * 
 * @author 00fly
 * @version [版本号, 2017年4月25日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Slf4j
@Component
@ConditionalOnNotWebApplication
public class ResourceReloadConfig implements SchedulingConfigurer
{
    PropertiesConfiguration jobConfig;
    
    Resource cron = new ClassPathResource("test/cron.properties");
    
    ResourceBundle job = ResourceBundle.getBundle("test/job");
    
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar)
    {
        // 配置公共Schedule线程池
        taskRegistrar.setScheduler(new ScheduledThreadPoolExecutor(8, new CustomizableThreadFactory("schedule-pool-")));
        
        // 配置TriggerTask
        taskRegistrar.addTriggerTask(new Runnable()
        {
            @Override
            public void run()
            {
                // 任务逻辑
                log.info("★★★★★★★ {} run ★★★★★★★", getClass().getName());
            }
        }, new Trigger()
        {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext)
            {
                String cron = readCronText();
                return new CronTrigger(cron).nextExecutionTime(triggerContext);
            }
        });
    }
    
    /**
     * 初始化
     */
    @PostConstruct
    public void init()
    {
        try
        {
            jobConfig = new PropertiesConfiguration("test/job.properties");
            FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
            strategy.setRefreshDelay(60000L);// 刷新周期1分钟
            jobConfig.setReloadingStrategy(strategy);
        }
        catch (ConfigurationException e)
        {
            log.error(e.getMessage(), e.getCause());
        }
    }
    
    /**
     * 3种方式读取CronText
     * 
     * @return
     */
    private String readCronText()
    {
        String cronText = "*/10 * * * * ?";
        Integer key = RandomUtils.nextInt(3);
        switch (key)
        {
            case 0:
                cronText = jobConfig.getString("schedule.myjob.cron");
                break;
            
            case 1:
                try
                {
                    cronText = IOUtils.toString(cron.getURL(), StandardCharsets.UTF_8);
                }
                catch (IOException e)
                {
                    log.error(e.getMessage(), e.getCause());
                }
                break;
            
            case 2:
                ResourceBundle.clearCache();
                cronText = job.getString("schedule.myjob.cron");
                break;
            
            default:
                break;
        }
        log.info("**** key: {} ==> {}", key, cronText);
        return cronText;
    }
}